An optimizing compiler may move (e.g., relocate) code (e.g., instruction, code fragment) in an executable to try to improve the performance of the executable. The compiler may record from where the code was moved and to where the code was moved. This may be done, for example, at the instruction level, at the block level, and so on.
Moving an instruction may change program semantics if the moved instruction raises an exception when executed in the new location. The semantics may change because the exception may be raised earlier than it would have been raised if the instruction was not moved. The semantics also may change if, for example, a computation is moved ahead of another statement to which the results of earlier statements and/or exceptions matter, even after an exception is raised. For example, consider a statement that updates a database with results from an earlier statement. In this case, the semantics of a program may be altered by an exception in the moved instruction unless the exception is delayed. Thus, to both preserve order and to preserve certain results, an exception raised by a moved instruction may be delayed.
FIG. 1 facilitates understanding this “out-of-order” exception raising and its effect on semantics. An executable may include, for example, code fragments 110, 120, 130, and 140. If code fragment 130 is moved ahead of code fragment 120, and if both code fragments would raise an exception, then the semantics of the executable would change. Absent the relocation, the exception from code fragment 120 would have been raised and handled before that of code fragment 130. However, after relocation, the exception from code fragment 130 would be raised and handled out of order. Since the order of the exceptions is altered, the executable may produce a different result. While FIG. 1 illustrates an out-of-order issue, it is to be appreciated that moving code may produce other issues, for example the result preservation issue described above.
To avoid this, optimizing compilers have been limited in that they may not have moved code around other code that may raise an exception. In some environments (e.g., PL/SQL (procedural language, structured query language)), where some if not all instructions may raise an exception, this may inhibit code motion entirely, which is a severe limitation.